home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / Issue67 / express / P10Build.pas next >
Pascal/Delphi Source File  |  2001-01-27  |  52KB  |  1,726 lines

  1. unit P10Build;
  2.  
  3. {$I+} { I/O checking is always on }
  4.  
  5. {$DEFINE UseIntegerOP}
  6.  
  7. // NOTE: Removed old and buggy code for Dyna conditional define - HV
  8.  
  9. interface
  10.  
  11. uses
  12.   Parser10,
  13.   SysUtils, Classes;
  14.  
  15. procedure ParseFunction( FunctionString: string; { the unparsed string }
  16.                          Variables: TStringlist; { list of variables }
  17.  
  18.                          { lists of available functions }
  19.                          FunctionOne,               { functions with ONE argument, e.g. exp() }
  20.                          FunctionTwo: TStringList;  { functions with TWO arguments, e.g. max(,) }
  21.  
  22.                          UsePascalNumbers: boolean; { true: -> Val; false: StrToFloat }
  23.  
  24.                          { return pointer to tree, number of performed operations and error state }
  25.                          var FirstOP : POperation;
  26.  
  27.                          var Error : boolean);
  28.                          { error actually is superfluous as we are now using exceptions }
  29.  
  30.  
  31.  
  32. implementation
  33.  
  34.  
  35. { helper functions }
  36.  
  37. var
  38.   CharTable:array[#0..#255] of byte;
  39.  
  40. (*function RemoveBlanks(const s: string): string;
  41. { deletes all blanks in s }
  42. var
  43.   i : integer;
  44. begin
  45.   Result := s;
  46.  
  47.   i := pos(' ', Result);
  48.   while i > 0 do
  49.   begin
  50.     delete(Result, i, 1);
  51.     i := pos(' ', Result);
  52.   end;
  53. end;*)
  54.  
  55. function TryStrToFloat(const S: string; var Value: Double): boolean;
  56. var
  57.   ExtValue: Extended;
  58. begin
  59.   Result := TextToFloat(PChar(S), ExtValue, fvExtended);
  60.   if Result then
  61.     Value := ExtValue;
  62. end;
  63.  
  64. function HackSetLength(var S: String; NewLen: Integer): integer;
  65. type
  66.   PInteger = ^Integer;
  67. begin
  68.   Result := Length(S);
  69.   {$IFDEF Win32}
  70.   PInteger(Longint(S)-4)^ := NewLen;
  71.   {$ELSE}
  72.   S[0] := Chr(NewLen);
  73.   {$ENDIF}
  74. end;
  75.  
  76. {$IFNDEF Win32}
  77. procedure SetLength(var S: String; NewLen: Integer);
  78. begin
  79.   S[0] := Chr(NewLen);
  80. end;
  81. {$ENDIF]
  82.  
  83. { case INSENSITIVE }
  84. procedure MakeCharTable;
  85. var
  86.   I: Integer;
  87. begin
  88.   for I := 0 to 255 do
  89.   begin
  90.     If (I > 64) and (I < 91) then
  91.       CharTable[Char(I)]:= I + 32
  92.     else
  93.       CharTable[Char(I)]:= I;
  94.   end;
  95. end;  { MakeCharTable }
  96.  
  97. function IPos(Pat, Text: PChar):Integer;
  98. var
  99.   RunPat, RunText, PosPtr: PChar;
  100. begin
  101.   Result:= 0;
  102.   RunPat:= Pat;
  103.   RunText:= Text;
  104.   while RunText^ <> #0 do
  105.   begin
  106.     if (CharTable[RunPat^] = CharTable[RunText^]) then
  107.       begin
  108.         PosPtr := RunText;
  109.         while RunPat^ <> #0 do begin
  110.           if (CharTable[RunPat^] <> CharTable[RunText^]) then break;
  111.           inc(RunPat); inc(RunText);
  112.         end;
  113.         if RunPat^ = #0 then
  114.           begin
  115.             Result:= PosPtr - Text +1;
  116.             break;
  117.           end;
  118.       end else inc(RunText);
  119.       RunPat:= Pat;
  120.   end;
  121. end; {IPos }
  122.  
  123. function IPosE(Pat, Text: PChar; StartPos, MaxPos: LongInt): Integer;
  124. var
  125.   AChar: char;
  126.  
  127.   RunPat,
  128.   RunText,
  129.   PosPtr: PChar;
  130. begin
  131.   Result:= 0;
  132.   RunPat:= Pat;
  133.  
  134.   RunText := Text + MaxPos;
  135.   AChar := RunText^;
  136.   RunText^ := #0;
  137.  
  138.   RunText := Text + StartPos -1;
  139.  
  140.   while RunText^ <> #0 do
  141.   begin
  142.     if (CharTable[RunPat^] = CharTable[RunText^]) then
  143.     begin
  144.       PosPtr := RunText;
  145.  
  146.       while RunPat^ <> #0 do
  147.       begin
  148.         if (CharTable[RunPat^] <> CharTable[RunText^]) then
  149.           break;
  150.  
  151.         inc(RunPat); inc(RunText);
  152.       end;
  153.  
  154.       if (RunPat^ = #0) then
  155.       begin
  156.         Result:= PosPtr - Text +1;
  157.         break;
  158.       end;
  159.  
  160.     end
  161.     else
  162.       inc(RunText);
  163.  
  164.     RunPat := Pat;
  165.   end;
  166.  
  167.   RunText := Text + MaxPos;
  168.   RunText^ := AChar;
  169.  
  170. end; {IPosE }
  171.  
  172. function FastPos(Sign: Char; ToScan: PChar): integer;
  173. var
  174.   Input: PChar;
  175. begin
  176.   Result := 0;
  177.   Input := ToScan;
  178.   while (ToScan^ <> #0) do
  179.   begin
  180.     if ToScan^ = Sign then
  181.     begin
  182.       Result := ToScan - Input;
  183.       break;
  184.     end;
  185.     inc(ToScan);
  186.   end;
  187. end;
  188.  
  189. {$IFDEF VER100}
  190. resourcestring
  191. {$ELSE}
  192. const
  193. {$ENDIF}
  194.   msgErrBlanks = 'Expression has blanks';
  195.   msgMissingBrackets = 'Missing brackets in expression (%s)';
  196.   msgParseError = 'Error parsing expression:';
  197.   msgNestings = 'Expression contains too many nestings';
  198.   msgTooComplex = 'Expression is too complex';
  199.   msgInternalError = 'TParser internal error';
  200.  
  201. const
  202.   TokenOperators = [ sum, diff, prod, divis, modulo, IntDiv,
  203.                      integerpower, realpower];
  204.  
  205. type
  206.   TermString = string;
  207.  
  208. procedure ParseFunction( FunctionString: string;
  209.                          Variables: TStringList;
  210.  
  211.                          FunctionOne,
  212.                          FunctionTwo: TStringList;
  213.  
  214.                          UsePascalNumbers: boolean;
  215.  
  216.                          var FirstOP: POperation;
  217.  
  218.                          var Error: boolean);
  219.  
  220.  
  221.           function CheckNumberBrackets(const s: string): integer; forward;
  222.           { checks whether number of ( = number of ) }
  223.  
  224.           function CheckNumber(const s: string; var FloatNumber: ParserFloat): boolean; forward;
  225.           { checks whether s is a number }
  226.  
  227.           function CheckVariable(const s: string; var VariableID: integer): boolean; forward;
  228.           { checks whether s is a variable string }
  229.  
  230.           function CheckTerm(var s1: string): boolean; forward;
  231.           { checks whether s is a valid term }
  232.  
  233.           function CheckBracket(const s: string; var s1: string): boolean; forward;
  234.           { checks whether s =(...(s1)...) and s1 is a valid term }
  235.  
  236.  
  237.  
  238.           function CheckNegate(const s: string; var s1: string): boolean; forward;
  239.           {checks whether s denotes the negative value of a valid operation}
  240.  
  241.  
  242.  
  243.           function CheckAdd(var s: string; var s1, s2: string): boolean; forward;
  244.           {checks whether + is the primary operation in s}
  245.  
  246.           function CheckSubtract(const s: string; var s1, s2: string): boolean; forward;
  247.           {checks whether - is the primary operation in s}
  248.  
  249.           function CheckMultiply(const s: string; var s1, s2: string): boolean; forward;
  250.           {checks whether * is the primary operation in s}
  251.  
  252. {$IFDEF UseIntegerOP}
  253.           function CheckIntegerDiv(const s: string; var s1, s2: string): boolean; forward;
  254.           {checks whether DIV is the primary TOperation in s}
  255.  
  256.           function CheckModulo(const s: string; var s1, s2: string): boolean; forward;
  257.           {checks whether MOD is the primary TOperation in s}
  258. {$ENDIF UseIntegerOP}
  259.  
  260.           function CheckRealDivision(const s: string; var s1, s2: string): boolean;  forward;
  261.           {checks whether / is the primary operation in s}
  262.  
  263.  
  264.  
  265.           function CheckFuncTwoVar(var s: string; var s1, s2: string): boolean; forward;
  266.           {checks whether s=f(s1,s2); s1,s2 being valid terms}
  267.  
  268.           function CheckFuncOneVar(var s: string; var s1: string): boolean; forward;
  269.           {checks whether s denotes the evaluation of a function fsort(s1)}
  270.  
  271.  
  272.           function CheckPower(const s: string; var s1, s2: string; var AToken: TToken): boolean; forward;
  273.  
  274.  
  275.           function CheckNumberBrackets(const s: string): integer;
  276.           {checks whether # of '(' equ. # of ')'}
  277.           var
  278.             counter: integer;
  279.           begin
  280.             Result := 0;
  281.  
  282.             counter := length(s);
  283.             while counter <> 0 do
  284.             begin
  285.               case s[counter] of
  286.                 '(': inc(Result);
  287.                 ')': dec(Result);
  288.               end;
  289.               dec(counter);
  290.             end;
  291.           end;
  292.  
  293.  
  294.           function CheckNumber(const s: string; var FloatNumber: ParserFloat):boolean;
  295.           {checks whether s is a number}
  296.           var
  297.             code: integer;
  298.           begin
  299.             if s = 'PI' then
  300.             begin
  301.               FloatNumber := Pi;
  302.               Result := true;
  303.             end
  304.             else
  305.             if s = '-PI' then
  306.             begin
  307.               FloatNumber := -Pi;
  308.               Result := true;
  309.             end
  310.             else
  311.             begin
  312.               if UsePascalNumbers then
  313.               begin
  314.                 val(s, FloatNumber, code);
  315.                 Result := code = 0;
  316.               end
  317.               else
  318.                 Result := TryStrToFloat(s, FloatNumber);
  319.             end;
  320.           end;
  321.  
  322.  
  323.           function CheckVariable(const s: string; var VariableID: integer): boolean;
  324.           {checks whether s is a variable string}
  325.           begin
  326.             Result := Variables.Find(s, VariableID);
  327.           end;
  328.  
  329.  
  330.           function CheckTerm(var s1: string) :boolean;
  331.           { checks whether s is a valid term }
  332.           var
  333.             s2, s3: TermString;
  334.             FloatNumber: ParserFloat;
  335.             fsort: TToken;
  336.             VariableID: integer;
  337.           begin
  338.             Result := false;
  339.  
  340.             if length(s1) = 0 then
  341.               exit;
  342.  
  343.             if CheckNumber(s1, FloatNumber) or
  344.                CheckVariable(s1, VariableID) or
  345.                CheckNegate(s1, s2) or
  346.                CheckAdd(s1, s2, s3) or
  347.                CheckSubtract(s1, s2, s3) or
  348.                CheckMultiply(s1, s2, s3) or
  349. {$IFDEF UseIntegerOP}
  350.                CheckIntegerDiv(s1, s2, s3) or
  351.                CheckModulo(s1, s2, s3) or
  352. {$ENDIF UseIntegerOP}
  353.                CheckRealDivision(s1, s2, s3) or
  354.                CheckPower(s1, s2, s3, fsort) or
  355.                CheckFuncTwoVar(s1, s2, s3) or
  356.                CheckFuncOneVar(s1, s2)
  357.             then
  358.               Result := true
  359.             else
  360.               if CheckBracket(s1, s2) then
  361.               begin
  362.                 s1 := s2;
  363.                 Result := true
  364.               end;
  365.  
  366.           end;
  367.  
  368.           function CheckBracket(const s: string; var s1: string): boolean;
  369.           {checks whether s =(...(s1)...) and s1 is a valid term}
  370.           var
  371.             SLen : integer;
  372.           begin
  373.             Result := false;
  374.  
  375.             SLen := Length(s);
  376.             if (SLen > 0) and (s[SLen] = ')') and (s[1] = '(') then
  377.             begin
  378.               s1 := copy(s, 2, SLen-2);
  379.               Result := CheckTerm(s1);
  380.             end;
  381.           end;
  382.  
  383.  
  384.           function CheckNegate(const s: string; var s1: string) :boolean;
  385.           {checks whether s denotes the negative value of a valid TOperation}
  386.           var
  387.             s2, s3: TermString;
  388.             fsort: TToken;
  389.             VariableID: integer;
  390.           begin
  391.             Result := false;
  392.  
  393.             if (length(s) <> 0) and (s[1] = '-') then
  394.             begin
  395.               
  396.               s1 := copy(s, 2, length(s)-1);
  397.               if CheckBracket(s1, s2) then
  398.               begin
  399.                 s1 := s2;
  400.                 Result := true;
  401.               end
  402.               else
  403.                 Result :=
  404.                   CheckVariable(s1, VariableID) or
  405.                   CheckPower(s1, s2, s3, fsort) or
  406.                   CheckFuncOneVar(s1, s2) or
  407.                   CheckFuncTwoVar(s1, s2, s3);
  408.  
  409.             end;
  410.           end;
  411.  
  412.  
  413.           function CheckAdd(var s: string; var s1, s2: string): boolean;
  414.           {checks whether '+' is the primary TOperation in s}
  415.           var
  416.             s3, s4: TermString;
  417.             OldLen,
  418.             i, j: integer;
  419.             FloatNumber: ParserFloat;
  420.             fsort: TToken;
  421.             VariableID: integer;
  422.           begin
  423.             Result := false;
  424.  
  425.             i := 0;
  426.             j := length(s);
  427.             repeat
  428.  
  429.               while i < j do
  430.               begin
  431.                 inc(i);
  432.                 if s[i] = '+' then
  433.                   break;
  434.               end;
  435.  
  436.               if (i > 1) and (i < j) then
  437.               begin
  438.  
  439.                 Result := false;
  440.  
  441.                 s2 := copy(s, i+1, j-i);
  442.                 if CheckNumberBrackets(s2) = 0 then
  443.                 begin
  444.                   OldLen := HackSetLength(S, i-1);
  445.                   Result := CheckNumberBrackets(s) = 0;
  446.                   HackSetLength(S, OldLen);
  447.  
  448.                   if Result then
  449.                   begin
  450.                     s1 := copy(s, 1, i-1);
  451.                     Result := CheckNumber(s1, FloatNumber) or CheckVariable(s1, VariableID);
  452.  
  453.  
  454.                     if not Result then
  455.                     begin
  456.                       Result := CheckBracket(s1, s3);
  457.                       if Result then
  458.                         s1 := s3;
  459.                     end;
  460.  
  461.                     if not Result then
  462.                       Result := CheckNegate(s1, s3) or
  463.                                 CheckSubtract(s1, s3, s4) or
  464.                                 CheckMultiply(s1, s3, s4) or
  465. {$IFDEF UseIntegerOP}
  466.                                 CheckIntegerDiv(s1, s3, s4) or
  467.                                 CheckModulo(s1, s3, s4) or
  468. {$ENDIF UseIntegerOP}
  469.                                 CheckRealDivision(s1, s3, s4) or
  470.                                 CheckPower(s1, s3, s4, fsort) or
  471.                                 CheckFuncOneVar(s1, s3) or
  472.                                 CheckFuncTwoVar(s1, s3, s4);
  473.  
  474.                     if Result then
  475.                     begin
  476.                       Result := CheckNumber(s2, FloatNumber) or CheckVariable(s2, VariableID);
  477.  
  478.                       if not Result then
  479.                       begin
  480.                         Result := CheckBracket(s2, s3);
  481.                         if Result then
  482.                           s2 := s3
  483.                         else
  484.                           Result := CheckAdd(s2, s3, s4) or
  485.                                     CheckSubtract(s2, s3, s4) or
  486.                                     CheckMultiply(s2, s3, s4) or
  487. {$IFDEF UseIntegerOP}
  488.                                     CheckIntegerDiv(s2, s3, s4) or
  489.                                     CheckModulo(s2, s3, s4) or
  490. {$ENDIF UseIntegerOP}
  491.                                     CheckRealDivision(s2, s3, s4) or
  492.                                     CheckPower(s2, s3, s4, fsort) or
  493.                                     CheckFuncOneVar(s2, s3) or
  494.                                     CheckFuncTwoVar(s2, s3, s4);
  495.                       end;
  496.                     end;
  497.  
  498.  
  499.                   end
  500.                 end
  501.               end
  502.               else
  503.                 break;
  504.  
  505.             until Result;
  506.           end;
  507.  
  508.  
  509.  
  510.           function CheckSubtract(const s: string; var s1, s2: string): boolean;
  511.           {checks whether '-' is the primary TOperation in s}
  512.           var
  513.             s3, s4: TermString;
  514.             i, j: integer;
  515.             FloatNumber: ParserFloat;
  516.             fsort: TToken;
  517.             VariableID: integer;
  518.           begin
  519.             Result := false;
  520.  
  521.             i := 1; { bugfix -1-1 }
  522.             j := length(s);
  523.  
  524.             repeat
  525.  
  526.               while i < j do { bugfix -1-1 }
  527.               begin
  528.                 inc(i);
  529.                 if s[i] = '-' then
  530.                   break;
  531.               end;
  532.  
  533.               if (i > 1) and (i < j) then
  534.               begin
  535.                 s1 := copy(s, 1, i-1);
  536.                 s2 := copy(s, i+1, j-i);
  537.  
  538.                 Result := (CheckNumberBrackets(s2)=0) and (CheckNumberBrackets(s1)=0);
  539.  
  540.                 if Result then
  541.                 begin
  542.                   Result := CheckNumber(s1, FloatNumber) or CheckVariable(s1, VariableID);
  543.  
  544.                   
  545.                   if not Result then
  546.                   begin
  547.                     Result := CheckBracket(s1, s3);
  548.                     if Result then
  549.                       s1 := s3;
  550.                   end;
  551.                   if not Result then
  552.                     Result := CheckNegate(s1, s3) or
  553.                               CheckSubtract(s1, s3, s4) or
  554.                               CheckMultiply(s1, s3, s4) or
  555. {$IFDEF UseIntegerOP}
  556.                               CheckIntegerDiv(s1, s3, s4) or
  557.                               CheckModulo(s1, s3, s4) or
  558. {$ENDIF UseIntegerOP}
  559.                               CheckRealDivision(s1, s3, s4) or
  560.                               CheckPower(s1, s3, s4, fsort) or
  561.                               CheckFuncOneVar(s1, s3) or
  562.                               CheckFuncTwoVar(s1, s3, s4);
  563.  
  564.                   if Result then
  565.                   begin
  566.                     Result := CheckNumber(s2, FloatNumber) or CheckVariable(s2, VariableID);
  567.  
  568.                     if not Result then
  569.                     begin
  570.                        Result := CheckBracket(s2, s3);
  571.                        if Result then
  572.                          s2 := s3
  573.                        else
  574.                          Result := CheckMultiply(s2, s3, s4) or
  575. {$IFDEF UseIntegerOP}
  576.                                    CheckIntegerDiv(s2, s3, s4) or
  577.                                    CheckModulo(s2, s3, s4) or
  578. {$ENDIF UseIntegerOP}
  579.                                    CheckRealDivision(s2, s3, s4) or
  580.                                    CheckPower(s2, s3, s4, fsort) or
  581.                                    CheckFuncOneVar(s2, s3) or
  582.                                    CheckFuncTwoVar(s2, s3, s4);
  583.                     end;
  584.                   end;
  585.  
  586.                 end;
  587.               end
  588.               else
  589.                 break;
  590.  
  591.             until Result;
  592.  
  593.           end;
  594.  
  595.  
  596.           function CheckMultiply(const s: string; var s1, s2: string): boolean;
  597.           {checks whether '*' is the primary TOperation in s}
  598.           var
  599.             s3, s4: TermString;
  600.             i, j: integer;
  601.             FloatNumber: ParserFloat;
  602.             fsort: TToken;
  603.             VariableID: integer;
  604.           begin
  605.             Result := false;
  606.  
  607.             i := 0;
  608.             j := length(s);
  609.  
  610.             repeat
  611.               while i < j do
  612.               begin
  613.                 inc(i);
  614.                 if s[i] = '*' then
  615.                   break;
  616.               end;
  617.  
  618.               if (i > 1) and (i < j) then
  619.               begin
  620.                 s1 := copy(s, 1, i-1);
  621.                 s2 := copy(s, i+1, j-i);
  622.  
  623.                 Result := (CheckNumberBrackets(s2)=0) and (CheckNumberBrackets(s1)=0);
  624.  
  625.                 if Result then
  626.                 begin
  627.                   Result := CheckNumber(s1, FloatNumber) or CheckVariable(s1, VariableID);
  628.  
  629.                   
  630.                   if not Result then
  631.                   begin
  632.                     Result := CheckBracket(s1, s3);
  633.                     if Result then
  634.                       s1 := s3;
  635.                   end;
  636.  
  637.                   if not Result then
  638.                     Result := CheckNegate(s1, s3) or
  639. {$IFDEF UseIntegerOP}
  640.                               CheckIntegerDiv(s1, s3, s4) or
  641.                               CheckModulo(s1, s3, s4) or
  642. {$ENDIF UseIntegerOP}
  643.                               CheckRealDivision(s1, s3, s4) or
  644.                               CheckPower(s1, s3, s4, fsort) or
  645.                               CheckFuncOneVar(s1, s3) or
  646.                               CheckFuncTwoVar(s1, s3, s4);
  647.  
  648.                   if Result then
  649.                   begin
  650.                     Result := CheckNumber(s2, FloatNumber) or CheckVariable(s2, VariableID);
  651.  
  652.                     if not Result then
  653.                     begin
  654.                       Result := CheckBracket(s2, s3);
  655.                       if Result then
  656.                         s2 := s3
  657.                       else
  658.                         Result := CheckMultiply(s2, s3, s4) or
  659. {$IFDEF UseIntegerOP}
  660.                                   CheckIntegerDiv(s2, s3, s4) or
  661.                                   CheckModulo(s2, s3, s4) or
  662. {$ENDIF UseIntegerOP}
  663.                                   CheckRealDivision(s2, s3, s4) or
  664.                                   CheckPower(s2, s3, s4, fsort) or
  665.                                   CheckFuncOneVar(s2, s3) or
  666.                                   CheckFuncTwoVar(s2, s3, s4);
  667.                     end;
  668.                   end;
  669.  
  670.                 end;
  671.               end
  672.               else
  673.                 break;
  674.  
  675.             until Result;
  676.           end;
  677.  
  678. {$IFDEF UseIntegerOP}
  679.           function CheckIntegerDiv(const s: string; var s1, s2: string): boolean;
  680.           {checks whether 'DIV' is the primary TOperation in s}
  681.           var
  682.             s3, s4: TermString;
  683.             i, j: integer;
  684.             VariableID: integer;
  685.             FloatNumber: ParserFloat;
  686.             fsort: TToken;
  687.           begin
  688.             Result := false;
  689.  
  690.             i := 0;
  691.  
  692.             repeat
  693.  
  694.               {$IFDEF Win32}
  695.                 // j := IPos('DIV', PChar(copy(s, i+1, length(s)-i)));
  696.  
  697.                 j := IPosE('DIV', PChar(s), i+1, length(s)-i);
  698.               {$ELSE}
  699.                 j := pos('DIV', copy(s, i+1, length(s)-i));
  700.               {$ENDIF Win32}
  701.  
  702.               if j > 0 then
  703.               begin
  704.  
  705.                 inc(i, j);
  706.                 if (i > 1) and (i < length(s)) then
  707.                 begin
  708.                   s1 := copy(s, 1, i-1);
  709.                   s2 := copy(s, i+3, length(s)-i-2);
  710.  
  711.                   Result := (CheckNumberBrackets(s2)=0) and (CheckNumberBrackets(s1)=0);
  712.  
  713.                   if Result then
  714.                   begin
  715.                     Result := CheckNumber(s1, FloatNumber) or CheckVariable(s1, VariableID);
  716.  
  717.                     if not Result then
  718.                     begin
  719.                       Result := CheckBracket(s1, s3);
  720.                       if Result then
  721.                         s1 := s3;
  722.                     end;
  723.  
  724.                     if not Result then
  725.                       Result := CheckNegate(s1, s3) or
  726.                                 CheckIntegerDiv(s1, s3, s4) or
  727.                                 CheckModulo(s1, s3, s4) or
  728.                                 CheckRealDivision(s1, s3, s4) or
  729.                                 CheckPower(s1, s3, s4, fsort) or
  730.                                 CheckFuncOneVar(s1, s3) or
  731.                                 CheckFuncTwoVar(s1, s3, s4);
  732.                     if Result then
  733.                     begin
  734.                       Result := CheckNumber(s2,FloatNumber) or CheckVariable(s2,VariableID);
  735.  
  736.                       if not Result then
  737.                       begin
  738.                         Result := CheckBracket(s2, s3);
  739.                         if Result then
  740.                           s2 := s3
  741.                         else
  742.                           Result := CheckPower(s2, s3, s4, fsort) or
  743.                                     CheckFuncOneVar(s2, s3) or
  744.                                     CheckFuncTwoVar(s2, s3, s4);
  745.                       end;
  746.                     end;
  747.  
  748.  
  749.                   end;
  750.                 end;
  751.               end;
  752.  
  753.             until Result or (j = 0) or (i >= length(s));
  754.           end;
  755.  
  756.           function CheckModulo(const s: string; var s1, s2: string): boolean;
  757.           {checks whether 'MOD' is the primary TOperation in s}
  758.           var
  759.             s3, s4: TermString;
  760.             i, j: integer;
  761.             VariableID: integer;
  762.             FloatNumber: ParserFloat;
  763.             fsort: TToken;
  764.           begin
  765.             Result := false;
  766.  
  767.             i := 0;
  768.             
  769.             repeat
  770.               {$IFDEF Win32}
  771.                 // j := IPos('MOD', PChar(copy(s, i+1, length(s)-i)));
  772.  
  773.                 j := IPosE('MOD', PChar(s), i+1, length(s)-i);
  774.               {$ELSE}
  775.                 j := pos('MOD', copy(s, i+1, length(s)-i));
  776.               {$ENDIF Win32}
  777.               if j > 0 then
  778.               begin
  779.  
  780.                 inc(i, j);
  781.                 if (i > 1) and (i < length(s)) then
  782.                 begin
  783.                   s1 := copy(s, 1, i-1);
  784.                   s2 := copy(s, i+3, length(s)-i-2);
  785.  
  786.                   Result := (CheckNumberBrackets(s2)=0) and (CheckNumberBrackets(s1)=0);
  787.  
  788.                   if Result then
  789.                   begin
  790.                     Result := CheckNumber(s1, FloatNumber) or CheckVariable(s1, VariableID);
  791.  
  792.                     if not Result then
  793.                     begin
  794.                       Result := CheckBracket(s1, s3);
  795.                       if Result then
  796.                         s1 := s3;
  797.                     end;
  798.                     if not Result then
  799.                       Result := CheckNegate(s1, s3) or
  800.                                 CheckIntegerDiv(s1, s3, s4) or
  801.                                 CheckModulo(s1, s3, s4) or
  802.                                 CheckRealDivision(s1, s3, s4) or
  803.                                 CheckPower(s1, s3, s4, fsort) or
  804.                                 CheckFuncOneVar(s1, s3) or
  805.                                 CheckFuncTwoVar(s1, s3, s4);
  806.  
  807.                     if Result then
  808.                     begin
  809.                       Result := CheckNumber(s2, FloatNumber) or CheckVariable(s2, VariableID);
  810.  
  811.                       if not Result then
  812.                       begin
  813.                         Result := CheckBracket(s2, s3);
  814.                         if Result then
  815.                           s2 := s3
  816.                         else
  817.                           Result := CheckPower(s2, s3, s4, fsort) or
  818.                                     CheckFuncOneVar(s2, s3) or
  819.                                     CheckFuncTwoVar(s2, s3, s4);
  820.  
  821.                       end
  822.                     end;
  823.  
  824.  
  825.                   end;
  826.                 end;
  827.               end;
  828.             until Result or (j = 0) or (i >= length(s));
  829.           end;
  830. {$ENDIF UseIntegerOP}
  831.  
  832.  
  833.           function CheckRealDivision(const s: string; var s1, s2: string): boolean;
  834.           {checks whether '/' is the primary TOperation in s}
  835.           var
  836.             s3, s4: TermString;
  837.             i, j: integer;
  838.             VariableID: integer;
  839.             FloatNumber: ParserFloat;
  840.             fsort: TToken;
  841.           begin
  842.             Result := false;
  843.  
  844.             i := 0;
  845.             j := length(s);
  846.  
  847.             repeat
  848.  
  849.               while i < j do
  850.               begin
  851.                 inc(i);
  852.                 if s[i] = '/' then
  853.                   break;
  854.               end;
  855.  
  856.               if (i > 1) and (i < j) then
  857.               begin
  858.                 s1 := copy(s, 1, i-1);
  859.                 s2 := copy(s, i+1, j-i);
  860.  
  861.                 Result := (CheckNumberBrackets(s2)=0) and (CheckNumberBrackets(s1)=0);
  862.  
  863.                 if Result then
  864.                 begin
  865.                   Result := CheckNumber(s1, FloatNumber) or CheckVariable(s1, VariableID);
  866.  
  867.                   
  868.                   if not Result then
  869.                   begin
  870.                     Result := CheckBracket(s1, s3);
  871.                     if Result then
  872.                       s1 := s3;
  873.                   end;
  874.  
  875.                   if not Result then
  876.                     Result := CheckNegate(s1, s3) or
  877. {$IFDEF UseIntegerOP}
  878.                               CheckIntegerDiv(s1, s3, s4) or
  879.                               CheckModulo(s1, s3, s4) or
  880. {$ENDIF UseIntegerOP}
  881.                               CheckRealDivision(s1, s3, s4) or
  882.                               CheckPower(s1, s3, s4, fsort) or
  883.                               CheckFuncOneVar(s1, s3) or
  884.                               CheckFuncTwoVar(s1, s3, s4);
  885.  
  886.                   if Result then
  887.                   begin
  888.                     Result := CheckNumber(s2, FloatNumber) or CheckVariable(s2, VariableID);
  889.  
  890.                     if not Result then
  891.                     begin
  892.                       Result := CheckBracket(s2, s3);
  893.                       if Result then
  894.                         s2 := s3
  895.                       else
  896.                         Result := CheckPower(s2, s3, s4, fsort) or
  897.                                   CheckFuncOneVar(s2, s3) or
  898.                                   CheckFuncTwoVar(s2, s3, s4);
  899.  
  900.                     end;
  901.                   end;
  902.  
  903.                 end;
  904.               end
  905.               else
  906.                 break;
  907.  
  908.             until Result;
  909.           end;
  910.  
  911.  
  912.           function CheckFuncTwoVar(var s: string; var s1, s2: string): boolean;
  913.           {checks whether s=f(s1,s2); s1,s2 being valid terms}
  914.  
  915.             function CheckComma(const s: string; var s1, s2: string): boolean;
  916.             var
  917.               i, j: integer;
  918.             begin
  919.               Result := false;
  920.  
  921.               i := 0;
  922.               j := length(s);
  923.               repeat
  924.  
  925.                 while i < j do
  926.                 begin
  927.                   inc(i);
  928.                   if s[i] = ',' then
  929.                     break;
  930.                 end;
  931.  
  932.                 if (i > 1) and (i < j) then
  933.                 begin
  934.                   s1 := copy(s, 1, i-1);
  935.                   if CheckTerm(s1) then
  936.                   begin
  937.                     s2 := copy(s, i+1, j-i);
  938.                     Result := CheckTerm(s2);
  939.                   end;
  940.  
  941.                 end
  942.                 else
  943.                   break;
  944.  
  945.               until Result;
  946.             end;
  947.  
  948.           var
  949.             OldLen,
  950.             SLen,
  951.             counter : integer;
  952.           begin
  953.  
  954.             Result := false;
  955.  
  956.             {$IFDEF Win32}
  957.               SLen := FastPos('(', PChar(s));
  958.             {$ELSE}
  959.               SLen := Pos('(', s);
  960.               dec(SLen);
  961.             {$ENDIF Win32}
  962.  
  963.             if (SLen > 0) and (s[length(s)] = ')') then
  964.             begin
  965.  
  966.               OldLen := HackSetLength(S, SLen);
  967.               Result := FunctionTwo.Find(s, counter);
  968.               HackSetLength(S, OldLen);
  969.  
  970. {              Result := FunctionTwo.Find(copy(s, 1, SLen), counter); }
  971.               if Result then
  972.               begin
  973.                 inc(SLen, 2);
  974.                 Result := CheckComma( copy(s, SLen, length(s)-SLen), s1, s2);
  975.               end;
  976.             end;
  977.           end;
  978.  
  979.  
  980.           function CheckFuncOneVar(var s: string; var s1: string): boolean;
  981.           {checks whether s denotes the evaluation of a function fsort(s1)}
  982.           var
  983.             OldLen,
  984.             counter: integer;
  985.             SLen: integer;
  986.           begin
  987.             Result := false;
  988.  
  989.             { change}
  990.             {$IFDEF Win32}
  991.               SLen := FastPos('(', PChar(s));
  992.             {$ELSE}
  993.               SLen := Pos('(', s);
  994.               dec(SLen);
  995.             {$ENDIF Win32}
  996.  
  997.             if (SLen > 0) then
  998.             begin
  999.               OldLen := HackSetLength(S, SLen);
  1000.               Result := FunctionOne.Find(s, counter);
  1001.               HackSetLength(S, OldLen);
  1002.  
  1003.               { Result := FunctionOne.Find(copy(s, 1, SLen), counter); }
  1004.               if Result then
  1005.               begin
  1006.                 Result := CheckBracket(copy(s, SLen+1, length(s)-SLen), s1);
  1007.               end;
  1008.             end;
  1009.           end;
  1010.  
  1011.           function CheckPower(const s: string; var s1, s2: string; var AToken: TToken): boolean;
  1012.           var
  1013.             s3, s4: TermString;
  1014.             i, j: integer;
  1015.             FloatNumber: ParserFloat;
  1016.             VariableID: integer;
  1017.           begin
  1018.             Result := false;
  1019.  
  1020.             i := 0;
  1021.             j := length(s);
  1022.             repeat
  1023.  
  1024.               while i < j do
  1025.               begin
  1026.                 inc(i);
  1027.                 if s[i] = '^' then
  1028.                   break;
  1029.               end;
  1030.  
  1031.               if (i > 1) and (i < j) then
  1032.               begin
  1033.                 s1 := copy(s, 1, i-1);
  1034.                 s2 := copy(s, i+1, j-i);
  1035.  
  1036.                 Result := (CheckNumberBrackets(s2)=0) and (CheckNumberBrackets(s1)=0);
  1037.  
  1038.                 if Result then
  1039.                 begin
  1040.                   Result := CheckNumber(s1, FloatNumber) or CheckVariable(s1, VariableID);
  1041.  
  1042.                   if not Result then
  1043.                   begin
  1044.                     Result := CheckBracket(s1, s3);
  1045.                     if Result then
  1046.                       s1 := s3;
  1047.                   end;
  1048.  
  1049.                   if not Result then
  1050.                     Result := CheckFuncOneVar(s1, s3) or
  1051.                               CheckFuncTwoVar(s1, s3, s4);
  1052.  
  1053.                   if Result then
  1054.                   begin
  1055.  
  1056.                     if CheckNumber(s2, FloatNumber) then
  1057.                     begin
  1058.                       i := trunc(FloatNumber);
  1059.  
  1060.                       if (i <> FloatNumber) then
  1061.                       begin
  1062.                         { this is a real number }
  1063.                         AToken := realpower;
  1064.                       end
  1065.                       else
  1066.                       begin
  1067.                         case i of
  1068.                           2: AToken := square;
  1069.                           3: AToken := third;
  1070.                           4: AToken := fourth;
  1071.                         else
  1072.                           AToken := integerpower;
  1073.                         end;
  1074.                       end;
  1075.                     end
  1076.                     else
  1077.                     begin
  1078.                       Result := CheckVariable(s2, VariableID);
  1079.  
  1080.                       if not Result then
  1081.                       begin
  1082.                         Result := CheckBracket(s2, s3);
  1083.                         if Result then
  1084.                           s2 := s3;
  1085.                       end;
  1086.  
  1087.                       if not Result then
  1088.                       begin
  1089.                         Result := CheckFuncOneVar(s2, s3) or
  1090.                                   CheckFuncTwoVar(s2, s3, s4);
  1091.                       end;
  1092.  
  1093.                       if Result then
  1094.                         AToken := realPower;
  1095.                     end;
  1096.                   end;
  1097.  
  1098.                 end;
  1099.               end
  1100.               else
  1101.                 break;
  1102.  
  1103.             until Result;
  1104.           end;
  1105.  
  1106.           function CreateOperation(const Term: TToken; const Proc: Pointer): POperation;
  1107.           begin
  1108.             new(Result);
  1109.             with Result^ do
  1110.             begin
  1111.               Arg1 := nil;
  1112.               Arg2 := nil;
  1113.               Dest := nil;
  1114.  
  1115.               NextOperation := nil;
  1116.  
  1117.               Token := Term;
  1118.  
  1119.               MathProc := TMathProcedure(Proc);
  1120.             end;
  1121.           end;
  1122.  
  1123. const
  1124.   BlankString = ' ';
  1125.  
  1126. type
  1127.   PTermRecord = ^TermRecord;
  1128.   TermRecord = record
  1129.                  { this usage of string is a bit inefficient,
  1130.                    as in 16bit always 256 bytes are consumed.
  1131.                    But since we
  1132.                    a) are allocating memory dynamically and
  1133.                    b) this will be released immediately when
  1134.                       finished with parsing
  1135.                    this seems to be OK
  1136.  
  1137.                    One COULD create a "TermClass" where this is handled }
  1138.                  StartString: string;
  1139.                  LeftString, RightString: string;
  1140.  
  1141.                  Token: TToken;
  1142.  
  1143.                  Position: array[1..3] of integer;
  1144.  
  1145.                  Next1,
  1146.                  Next2,
  1147.                  Previous: PTermRecord;
  1148.                end;
  1149.  
  1150.  
  1151. const
  1152.   { side effect: for each bracketing level added
  1153.       SizeOf(integer) bytes additional stack usage
  1154.       maxLevelWidth*SizeOf(Pointer) additional global memory used }
  1155.   maxBracketLevels = 20;
  1156.  
  1157.   { side effect: for each additional (complexity) level width
  1158.       maxBracketLevels*SizeOf(Pointer) additional global memory used }
  1159.   maxLevelWidth = 50;
  1160. type
  1161.   LevelArray = array[0..maxBracketLevels] of integer;
  1162.  
  1163.   OperationPointerArray = array[0..maxBracketLevels, 1..maxLevelWidth] of POperation;
  1164.   POperationPointerArray = ^OperationPointerArray;
  1165.  
  1166. var
  1167.   Matrix: POperationPointerArray;
  1168.  
  1169.   { bracket positions }
  1170.   CurrentBracket,
  1171.   i,
  1172.   CurBracketLevels: integer;
  1173.  
  1174.   BracketLevel: LevelArray;
  1175.  
  1176.   LastOP: POperation;
  1177.   FloatNumber: ParserFloat;
  1178.   VariableID: integer;
  1179.  
  1180.  
  1181.   ANewTerm, { need this particlar pointer to guarantee a good, flawless memory cleanup in except }
  1182.  
  1183.   FirstTerm,
  1184.   Next1Term,
  1185.   Next2Term,
  1186.   LastTerm: PTermRecord;
  1187.  
  1188.   counter1,
  1189.   counter2: integer;
  1190. begin
  1191.   { initialize local variables for safe checking in try..finally..end}
  1192.  
  1193.   { FirstTerm := nil; } { not necessary since not freed in finally }
  1194.   LastTerm := nil;
  1195.   ANewTerm := nil;
  1196.   Next1Term := nil;
  1197.   Next2Term := nil;
  1198.  
  1199.   Error := false;
  1200.  
  1201.   FillChar(BracketLevel, SizeOf(BracketLevel), 0); { initialize bracket array }
  1202.   BracketLevel[0] := 1;
  1203.   CurBracketLevels := 0;
  1204.  
  1205.   new(Matrix);
  1206.  
  1207.   try { this block protects the whole of ALL assignments...}
  1208.     FillChar(Matrix^, SizeOf(Matrix^), 0);
  1209.  
  1210.     new(ANewTerm);
  1211.     with ANewTerm^ do
  1212.     begin
  1213.  
  1214.       StartString := UpperCase(FunctionString);
  1215.  
  1216.       { remove leading and trailing spaces }
  1217.       counter1 := 1;
  1218.       counter2 := length(StartString);
  1219.       while counter1 <= counter2 do
  1220.         if StartString[counter1] <> ' ' then
  1221.           break
  1222.         else
  1223.           inc(counter1);
  1224.  
  1225.       counter2 := length(StartString);
  1226.       while counter2 > counter1 do
  1227.         if StartString[counter2] <> ' ' then
  1228.           break
  1229.         else
  1230.           dec(counter2);
  1231.  
  1232.       StartString := Copy(StartString, counter1, counter2 - counter1 + 1);
  1233.  
  1234.       { change }
  1235.       {$IFDEF Win32}
  1236.          if FastPos(' ', PChar(StartString)) <> 0 then
  1237.       {$ELSE}
  1238.         if Pos(' ', StartString) > 0 then
  1239.       {$ENDIF Win32}
  1240.         raise EExpressionHasBlanks.Create(msgErrBlanks);
  1241.       {
  1242.       Old code:
  1243.  
  1244.          StartString := RemoveBlanks(UpperCase(FunctionString));
  1245.  
  1246.       ...do not use! Using it would create the following situation:
  1247.  
  1248.          Passed string:   "e xp(12)"
  1249.          Modified string: "exp(12)"
  1250.  
  1251.       This MAY or may not be the desired meaning - there may well exist
  1252.       a variable "e" and a function "xp" and just the operator would be missing.
  1253.  
  1254.       Conclusion: the above line has the potential of changing the meaning
  1255.                   of an expression.
  1256.       }
  1257.                                                  
  1258.       i := CheckNumberBrackets(StartString);
  1259.       if i > 0 then
  1260.         raise EMissMatchingBracket.CreateFmt(msgMissingBrackets, ['")"', i])
  1261.       else
  1262.         if i < 0 then
  1263.           raise EMissMatchingBracket.CreateFmt(msgMissingBrackets, ['"("', i]);
  1264.  
  1265.       { remove enclosing brackets, e.g. ((pi)) }
  1266.       while CheckBracket(StartString, FunctionString) do
  1267.         StartString := FunctionString;
  1268.  
  1269.       LeftString := BlankString;
  1270.       RightString := BlankString;
  1271.  
  1272.       Token := variab;
  1273.  
  1274.       Next1 := nil;
  1275.       Next2 := nil;
  1276.       Previous := nil;
  1277.     end;
  1278.  
  1279.     Matrix[0,1] := CreateOperation(variab, nil);
  1280.  
  1281.     LastTerm := ANewTerm;
  1282.     FirstTerm := ANewTerm;
  1283.     ANewTerm := nil;
  1284.  
  1285.     with LastTerm^ do
  1286.     begin
  1287.       Position[1] := 0;
  1288.       Position[2] := 1;
  1289.       Position[3] := 1;
  1290.     end;
  1291.  
  1292.     repeat
  1293.  
  1294.       repeat
  1295.  
  1296.         with LastTerm^ do
  1297.         begin
  1298.  
  1299.           CurrentBracket := Position[1];
  1300.           i := Position[2];
  1301.  
  1302.           if Next1 = nil then
  1303.           begin
  1304.             if CheckNumber(StartString, FloatNumber) then
  1305.             begin
  1306.               Token := constant;
  1307.               if Position[3] = 1 then
  1308.               begin
  1309.                 new(Matrix[CurrentBracket, i]^.Arg1);
  1310.                 Matrix[CurrentBracket, i]^.Arg1^ := FloatNumber;
  1311.               end
  1312.               else
  1313.               begin
  1314.                 new(Matrix[CurrentBracket, i]^.Arg2);
  1315.                 Matrix[CurrentBracket, i]^.Arg2^ := FloatNumber;
  1316.               end;
  1317.             end
  1318.             else
  1319.             begin
  1320.               if CheckVariable(StartString, VariableID) then
  1321.               begin
  1322.                 Token := variab;
  1323.  
  1324.                 if Position[3] = 1 then
  1325.                   Matrix[CurrentBracket, i]^.Arg1 := PParserFloat(Variables.Objects[VariableID])
  1326.                 else
  1327.                   Matrix[CurrentBracket, i]^.Arg2 := PParserFloat(Variables.Objects[VariableID])
  1328.               end
  1329.               else
  1330.               begin
  1331.                 if CheckNegate(StartString, LeftString) then
  1332.                   Token := minus
  1333.                 else
  1334.                 begin
  1335.                   if CheckAdd(StartString, LeftString, RightString) then
  1336.                     Token := sum
  1337.                   else
  1338.                   begin
  1339.                     if CheckSubtract(StartString, LeftString, RightString) then
  1340.                       Token := diff
  1341.                     else
  1342.                     begin
  1343.                       if CheckMultiply(StartString, LeftString, RightString) then
  1344.                         Token := prod
  1345.                       else
  1346.                       begin
  1347. {$IFDEF UseIntegerOP}
  1348.                         if CheckIntegerDiv(StartString, LeftString, RightString) then
  1349.                           Token := IntDiv
  1350.                         else
  1351.                         begin
  1352.                           if CheckModulo(StartString, LeftString, RightString) then
  1353.                             Token := modulo
  1354.                           else
  1355. {$ELSE}
  1356.                         begin
  1357. {$ENDIF UseIntegerOP}
  1358.                           begin
  1359.                             if CheckRealDivision(StartString, LeftString, RightString) then
  1360.                               Token := divis
  1361.                             else
  1362.                             begin
  1363.                               if not CheckPower(StartString, LeftString, RightString, Token) then
  1364.                               begin
  1365.                                 if CheckFuncOneVar(StartString, LeftString) then
  1366.                                   Token := FuncOneVar
  1367.                                 else
  1368.                                 begin
  1369.                                   if CheckFuncTwoVar(StartString, LeftString, RightString) then
  1370.                                     Token := FuncTwoVar
  1371.                                   else
  1372.                                   begin
  1373.                                     Error := true; {with an exception raised this is meaningless...}
  1374.                                     if (LeftString = BlankString) and (RightString = BlankString) then
  1375.                                       raise ESyntaxError.CreateFmt(
  1376.                                          msgParseError+#13'%s', [StartString]
  1377.                                                                    )
  1378.                                     else
  1379.                                       raise ESyntaxError.CreateFmt(
  1380.                                          msgParseError+#13'%s'#13'%s', [Leftstring, RightString]
  1381.                                                                    )
  1382.                                   end;
  1383.                                 end;
  1384.                               end;
  1385.                             end;
  1386.                           end;
  1387.                         end;
  1388.                       end;
  1389.                     end;
  1390.                   end;
  1391.                 end;
  1392.               end;
  1393.             end;
  1394.           end;
  1395.         end; { with LastTerm^ }
  1396.  
  1397.  
  1398.         if LastTerm^.Token in ( [minus, square, third, fourth, FuncOneVar, FuncTwoVar] + TokenOperators) then
  1399.         begin
  1400.           if LastTerm^.Next1 = nil then
  1401.           begin
  1402.             try
  1403.               Next1Term := nil;
  1404.               new(Next1Term);
  1405.  
  1406.               inc(CurrentBracket);
  1407.               if CurrentBracket > maxBracketLevels then
  1408.               begin
  1409.                 Error := true;
  1410.                 raise ETooManyNestings.Create(msgNestings);
  1411.               end;
  1412.  
  1413.               i := BracketLevel[CurrentBracket] + 1;
  1414.               if i > maxLevelWidth then
  1415.               begin
  1416.                 Error := true;
  1417.                 raise EExpressionTooComplex.Create(msgTooComplex);
  1418.               end;
  1419.  
  1420.               if CurBracketLevels < CurrentBracket then
  1421.                 CurBracketLevels := CurrentBracket;
  1422.  
  1423.               with Next1Term^ do
  1424.               begin
  1425.                 StartString := LastTerm^.LeftString;
  1426.                 LeftString := BlankString;
  1427.                 RightString := BlankString;
  1428.  
  1429.                 Position[1] := CurrentBracket;
  1430.                 Position[2] := i;
  1431.                 Position[3] := 1;
  1432.  
  1433.                 Token := variab;
  1434.  
  1435.                 Previous := LastTerm;
  1436.                 Next1 := nil;
  1437.                 Next2 := nil;
  1438.               end;
  1439.  
  1440.               with LastTerm^ do
  1441.               begin
  1442.                 case Token of
  1443.                   FuncOneVar:
  1444.                     with FunctionOne do
  1445.                     begin
  1446.                       {$IFDEF Win32}
  1447.                         SetLength(StartString, FastPos('(', PChar(StartString)));
  1448.                       {$ELSE}
  1449.                         StartString[0] := chr(Pos('(', StartString)-1);
  1450.                       {$ENDIF Win32}
  1451.                       Find(StartString, counter1);
  1452.  
  1453.                       Matrix[CurrentBracket, i] := CreateOperation(
  1454.                                        Token, Objects[counter1] );
  1455.  
  1456.                     end;
  1457.  
  1458.  
  1459.                   FuncTwoVar:
  1460.                     with FunctionTwo do
  1461.                     begin
  1462.                       {$IFDEF Win32}
  1463.                         SetLength(StartString, FastPos('(', PChar(StartString)));
  1464.                       {$ELSE}
  1465.                         StartString[0] := chr(Pos('(', StartString)-1);
  1466.                       {$ENDIF Win32}
  1467.                       Find(StartString, counter1);
  1468.  
  1469.                       Matrix[CurrentBracket, i] := CreateOperation(
  1470.                                        Token, Objects[counter1] );
  1471.                     end;
  1472.                 else
  1473.                   Matrix[CurrentBracket, i] := CreateOperation(Token, nil);
  1474.                 end;
  1475.  
  1476.                 new(Matrix[CurrentBracket, i]^.Dest);
  1477.                 Matrix[CurrentBracket, i]^.Dest^ := 0;
  1478.  
  1479.                 if Position[3] = 1 then
  1480.                   Matrix[Position[1], Position[2]]^.Arg1 :=
  1481.                     Matrix[CurrentBracket, i]^.Dest
  1482.                 else
  1483.                   Matrix[Position[1], Position[2]]^.Arg2 :=
  1484.                     Matrix[CurrentBracket, i]^.Dest;
  1485.  
  1486.                 Next1 := Next1Term;
  1487.                 Next1Term := nil;
  1488.               end;
  1489.  
  1490.               if LastTerm^.Token in [minus, square, third, fourth, FuncOneVar] then
  1491.               inc(BracketLevel[CurrentBracket]);
  1492.  
  1493.             except
  1494.               if assigned(Next1Term) then
  1495.               begin
  1496.                 dispose(Next1Term);
  1497.                 Next1Term := nil;
  1498.               end;
  1499.               raise;
  1500.             end;
  1501.  
  1502.           end
  1503.  
  1504.           else
  1505.           begin
  1506.             if LastTerm^.Token in (TokenOperators + [FuncTwoVar]) then
  1507.             begin
  1508.               try
  1509.                 Next2Term := nil;
  1510.                 new(Next2Term);
  1511.  
  1512.                 inc(CurrentBracket);
  1513.                 if CurrentBracket > maxBracketLevels then
  1514.                 begin
  1515.                   Error := true;
  1516.                   raise ETooManyNestings.Create(msgNestings);
  1517.                 end;
  1518.  
  1519.                 i := BracketLevel[CurrentBracket] + 1;
  1520.                 if i > maxLevelWidth then
  1521.                 begin
  1522.                   Error := true;
  1523.                   raise EExpressionTooComplex.Create(msgTooComplex);
  1524.                 end;
  1525.  
  1526.                 if CurBracketLevels < CurrentBracket then
  1527.                   CurBracketLevels := CurrentBracket;
  1528.  
  1529.                 with Next2Term^ do
  1530.                 begin
  1531.                   StartString := LastTerm^.RightString;
  1532.  
  1533.                   LeftString := BlankString;
  1534.                   RightString := BlankString;
  1535.  
  1536.                   Token := variab;
  1537.  
  1538.                   Position[1] := CurrentBracket;
  1539.                   Position[2] := i;
  1540.                   Position[3] := 2;
  1541.  
  1542.                   Previous := LastTerm;
  1543.                   Next1 := nil;
  1544.                   Next2 := nil;
  1545.                 end;
  1546.  
  1547.                 LastTerm^.Next2 := Next2Term;
  1548.                 Next2Term := nil;
  1549.                 inc(BracketLevel[CurrentBracket]);
  1550.  
  1551.               except
  1552.                 if assigned(Next2Term) then
  1553.                 begin
  1554.                   dispose(Next2Term);
  1555.                   Next2Term := nil;
  1556.                 end;
  1557.  
  1558.                 raise;
  1559.               end;
  1560.             end
  1561.             else
  1562.               raise EParserInternalError.Create(msgInternalError);
  1563.           end;
  1564.         end;
  1565.  
  1566.  
  1567.         with LastTerm^ do
  1568.           if Next1 = nil then
  1569.           begin
  1570.           { we are done with THIS loop }
  1571.             break;
  1572.           end
  1573.           else
  1574.             if Next2 = nil then
  1575.               LastTerm := Next1
  1576.             else
  1577.               LastTerm := Next2;
  1578.  
  1579.       until false; { endless loop, break'ed 7 lines above }
  1580.  
  1581.       if LastTerm = FirstTerm then
  1582.       begin
  1583.         dispose(LastTerm);
  1584.         FirstTerm := nil;
  1585.         break; { OK - that is it, we did not find any more terms}
  1586.       end;
  1587.  
  1588.       repeat
  1589.         with LastTerm^ do { cannot use "with LastTerm^" OUTSIDE loop }
  1590.         begin
  1591.           if Next1 <> nil then
  1592.           begin
  1593.             dispose(Next1);
  1594.             Next1 := nil;
  1595.           end;
  1596.  
  1597.           if Next2 <> nil then
  1598.           begin
  1599.             dispose(Next2);
  1600.             Next2 := nil;
  1601.           end;
  1602.  
  1603.           LastTerm := Previous;
  1604.         end;
  1605.       until ((LastTerm^.Token in (TokenOperators + [FuncTwoVar])) and (LastTerm^.Next2 = nil)) or
  1606.             (LastTerm = FirstTerm);
  1607.  
  1608.       with FirstTerm^ do
  1609.       if (LastTerm = FirstTerm) and
  1610.             (  (Token in [minus, square, third, fourth, FuncOneVar]) or
  1611.                ((Token in (TokenOperators + [FuncTwoVar])) and Assigned(Next2))
  1612.             ) then
  1613.       begin
  1614.         break;
  1615.       end;
  1616.  
  1617.  
  1618.     until false;
  1619.  
  1620.  
  1621.     { after having built the expression matrix, translate it into a tree/list }
  1622.  
  1623.     with FirstTerm^ do
  1624.       if FirstTerm <> nil then
  1625.       begin
  1626.         if Next1 <> nil then
  1627.         begin
  1628.           dispose(Next1);
  1629.           Next1 := nil;
  1630.         end;
  1631.  
  1632.         if Next2 <> nil then
  1633.         begin
  1634.           dispose(Next2);
  1635.           Next2 := nil;
  1636.         end;
  1637.  
  1638.         dispose(FirstTerm);
  1639.       end;
  1640.  
  1641.     BracketLevel[0] := 1;
  1642.  
  1643.     if CurBracketLevels = 0 then
  1644.     begin
  1645.       FirstOP := Matrix[0,1];
  1646.       Matrix[0,1] := nil;
  1647.       FirstOP^.Dest := FirstOP^.Arg1;
  1648.     end
  1649.     else
  1650.     begin
  1651.  
  1652.       FirstOP := Matrix[CurBracketLevels, 1];
  1653.       LastOP := FirstOP;
  1654.  
  1655.       for counter2 := 2 to BracketLevel[CurBracketLevels] do
  1656.       begin
  1657.         LastOP^.NextOperation := Matrix[CurBracketLevels, counter2];
  1658.         LastOP := LastOP^.NextOperation;
  1659.       end;
  1660.  
  1661.  
  1662.       for counter1 := CurBracketLevels-1 downto 1 do
  1663.         for counter2 := 1 to BracketLevel[counter1] do
  1664.         begin
  1665.           LastOP^.NextOperation := Matrix[counter1, counter2];
  1666.           LastOP := LastOP^.NextOperation;
  1667.         end;
  1668.  
  1669.  
  1670.       with Matrix[0,1]^ do
  1671.       begin
  1672.         Arg1 := nil;
  1673.         Arg2 := nil;
  1674.         Dest := nil;
  1675.       end;
  1676.  
  1677.       dispose(Matrix[0,1]);
  1678.     end;
  1679.  
  1680.     dispose(Matrix);
  1681.  
  1682.   except
  1683.     if Assigned(Matrix) then
  1684.     begin
  1685.       if Matrix[0,1] <> nil then
  1686.         dispose(Matrix[0,1]);
  1687.  
  1688.       for counter1 := CurBracketLevels downto 1 do
  1689.         for counter2 := 1 to BracketLevel[counter1] do
  1690.           if Matrix[counter1, counter2] <> nil then
  1691.  
  1692.             dispose(Matrix[counter1, counter2]);
  1693.  
  1694.       dispose(Matrix);
  1695.     end;
  1696.  
  1697.     if Assigned(Next1Term) then
  1698.       dispose(Next1Term);
  1699.  
  1700.     if Assigned(Next2Term) then
  1701.       dispose(Next2Term);
  1702.  
  1703. {   do NOT kill this one at it is possibly the same as LastTerm (see below)!
  1704.     if Assigned(FirstTerm) then
  1705.       dispose(FirstTerm);
  1706.  
  1707.     instead, DO kill ANewTerm, which will only be <> nil if it has NOT passed
  1708.     its value to some other pointer already so it can safely be freed
  1709. }
  1710.     if Assigned(ANewTerm) then
  1711.       dispose(ANewTerm);
  1712.  
  1713.     if Assigned(LastTerm) and (LastTerm <> Next2Term) and (LastTerm <> Next1Term) then
  1714.       dispose(LastTerm);
  1715.  
  1716.     FirstOP := nil;
  1717.  
  1718.     raise; { re-raise exception }
  1719.   end;
  1720. end;
  1721.  
  1722. initialization
  1723.   MakeCharTable;
  1724. end.
  1725.  
  1726.